package blue.web.dao.service;

import blue.tools.constants.BlueContants;
import blue.commons.enums.TaskTypeEnum;
import blue.dao.base.BaseMapper;
import blue.erp.model.BlueCourse;
import blue.erp.model.SysUser;
import blue.splitclass.dao.SplitClassLayerCourseMapper;
import blue.splitclass.model.*;
import blue.tools.commons.BlueStringUtils;
import blue.web.commons.service.ExcelService;
import blue.web.commons.service.OSSService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class SplitClassLayerCourseService extends BaseService {

    @Autowired
    private SplitClassLayerCourseMapper splitClassLayerCourseMapper;

    @Autowired
    private ElectiveStudentSelectedService electiveStudentSelectedService;

    @Autowired
    private BlueCourseService blueCourseService;

    @Autowired
    private ElectiveTaskService electiveTaskService;

    @Autowired
    private SplitClassLayerInfoService splitClassLayerInfoService;

    @Autowired
    private ExcelService excelService;

    @Autowired
    private ElectivePublishCourseService electivePublishCourseService;

    @Autowired
    private SplitClassTimeService splitClassTimeService;

    @Autowired
    private ElectiveRuleService electiveRuleService;

    @Autowired
    private OSSService ossService;

    @Autowired
    private BlueClassService blueClassService;

    @Autowired
    private SplitClassLayerStudentService splitClassLayerStudentService;

    private static final String ossTempletPrefix="CLASS_LAYER_COURSE_OSS_TEMPLET_";


    public int deleteBatch(String ids, SysUser sysUser) {
        List idList= BlueStringUtils.convertString2Num(ids,",");
        SplitClassLayerCourseExample example=new SplitClassLayerCourseExample();
        example.createCriteria().andIdIn(idList);
        clearCache(sysUser.getSchoolid(),null);
        return this.getBaseMapper().deleteByExample(example);
    }


    public int save(SplitClassLayerCourse record) {
        if(record==null || record.getTaskId()==null){
            return 0;
        }

        SplitClassLayerCourseExample example=new SplitClassLayerCourseExample();
        SplitClassLayerCourseExample.Criteria criteria=example.createCriteria().andSchoolidEqualTo(record.getSchoolid());

        if(record.getTaskId()!=null){
            criteria.andTaskIdEqualTo(record.getTaskId());
        }
        if(record.getCourseId()!=null){
            criteria.andCourseIdEqualTo(record.getCourseId());
        }

        //课程配置 和 结果配置，这块可以做细化逻辑
        if(StringUtils.isNotBlank(record.getLayerConfig())){
            record.setLayerResultConfig(record.getLayerConfig());
        }
        clearCache(record.getSchoolid(),record.getTaskId());
        return this.baseSave(record,example);

    }

    /**
     * 创建课程分层模板
     * @param record
     * @return
     */
    public String getCourseLayerTemplet(SplitClassLayerCourse record){

        if(record==null || record.getTaskId()==null || record.getSchoolid()==null){
            return null;
        }

        Object cacheObject=redisService.getValue(String.format("%s_%s_%s",ossTempletPrefix,record.getSchoolid(),record.getTaskId()));
        if(cacheObject==null){

            SplitClassLayerInfo splitClassLayerInfo=splitClassLayerInfoService.selectByTaskId(record.getTaskId(),record.getSchoolid());

            SplitClassLayerCourse selectParam=new SplitClassLayerCourse();
            selectParam.setTaskId(record.getTaskId());
            selectParam.setSchoolid(record.getSchoolid());
            List<SplitClassLayerCourse> layerCourseList=selectByObject(selectParam,true);
            if(CollectionUtils.isEmpty(layerCourseList) || splitClassLayerInfo==null || StringUtils.isBlank(splitClassLayerInfo.getNames())){
                return null;
            }
            Map<String, Object> row1 = new LinkedHashMap<>();
            row1.put("姓名","张三");
            row1.put("学号","no001");
            int count=0;
            String[] layerInfos=splitClassLayerInfo.getNames().split(",");
            for(SplitClassLayerCourse splitClassLayerCourse:layerCourseList){
                row1.put(splitClassLayerCourse.getCourseName(),layerInfos[count%layerInfos.length]);
                count++;
            }

            row1.put(String.format("备注:层次只能从 [%s] 这个集合选取，这个集合的数据可以从 科目分层设置里面设置",splitClassLayerInfo.getNames()),"");

            List data=new LinkedList();
            data.add(row1);
            String filename=String.format("split_course_templet_%s.xls",record.getTaskId());
            int result=excelService.writeData2Excel(data,null,BlueContants.import_excel_courselayer,filename,BlueContants.oss_blue_erp_ui);
            if(result>0){

                String resultUrl=String.format("%s/%s",BlueContants.oss_shanghai_url,filename);
                redisService.setValue(String.format("%s_%s_%s",ossTempletPrefix,record.getSchoolid(),record.getTaskId()),resultUrl);

                return resultUrl;
            }

        }else {
            return (String) cacheObject;
        }

        return null;
    }

    public List<SplitClassLayerCourse> selectByObject(SplitClassLayerCourse record,boolean showCourseName){

        if(record.getTaskId()==null){
            return null;
        }

        SplitClassLayerCourseExample example=new SplitClassLayerCourseExample();
        SplitClassLayerCourseExample.Criteria criteria=example.createCriteria().andSchoolidEqualTo(record.getSchoolid()).andTaskIdEqualTo(record.getTaskId());

        if(record.getId()!=null){
            criteria.andIdEqualTo(record.getId());
        }

        List<SplitClassLayerCourse>  layerCourseList=this.select(example);

        if (CollectionUtils.isNotEmpty(layerCourseList)) {

            for (SplitClassLayerCourse splitClassLayerCourse : layerCourseList) {
                if (showCourseName) {
                    BlueCourse blueCourse = blueCourseService.selectByPrimaryKey(splitClassLayerCourse.getCourseId(), record.getSchoolid(), false);
                    if (blueCourse != null) {
                        splitClassLayerCourse.setCourseName(blueCourse.getName());
                    }
                }
                splitClassLayerCourse=addLayerName(splitClassLayerCourse);
            }
        }

        return layerCourseList;
    }

    public List<SplitClassLayerCourse> selectByTaskId(Long taskId,Long schoolId){

        if(taskId==null || schoolId==null){
            return null;
        }

        SplitClassLayerCourse splitClassLayerCourse=new SplitClassLayerCourse();
        splitClassLayerCourse.setTaskId(taskId);
        splitClassLayerCourse.setSchoolid(schoolId);

        return selectByObject(splitClassLayerCourse,true);
    }


    public SplitClassLayerCourse addLayerName(SplitClassLayerCourse splitClassLayerCourse){

        if(splitClassLayerCourse==null || splitClassLayerCourse.getTaskId()==null || splitClassLayerCourse.getSchoolid()==null){
            return splitClassLayerCourse;
        }

        SplitClassLayerInfo splitClassLayerInfo=splitClassLayerInfoService.selectByTaskId(splitClassLayerCourse.getTaskId(),splitClassLayerCourse.getSchoolid());

        if(splitClassLayerInfo==null || StringUtils.isBlank(splitClassLayerInfo.getNames())){
            return splitClassLayerCourse;
        }

        String[] layerNames=splitClassLayerInfo.getNames().split(",");

        String layConfig=splitClassLayerCourse.getLayerConfig();
        if(StringUtils.isNotBlank(layConfig)){
            JSONArray layConfigArray=JSONArray.parseArray(layConfig);
            for(int i=0;i<layConfigArray.size();i++){
                JSONObject jsonObject=layConfigArray.getJSONObject(i);
                if(i<layerNames.length){
                    jsonObject.put("name",layerNames[i]);
                }
            }
            splitClassLayerCourse.setLayerConfig(JSONArray.toJSONString(layConfigArray));
        }

        String layerResultConfig=splitClassLayerCourse.getLayerResultConfig();
        if(StringUtils.isNotBlank(layerResultConfig)){
            JSONArray layConfigArray=JSONArray.parseArray(layerResultConfig);
            for(int i=0;i<layConfigArray.size();i++){
                JSONObject jsonObject=layConfigArray.getJSONObject(i);
                if(i<layerNames.length){
                    jsonObject.put("name",layerNames[i]);
                }
            }
            splitClassLayerCourse.setLayerResultConfig(JSONArray.toJSONString(layConfigArray));
        }

        return splitClassLayerCourse;

    }


    /**
     * 根据taskId获取课程分层待选列表
     */
    public List<SplitClassLayerCourse> selectLayerOptions(Long taskId,Long schoolId){

        if(taskId==null || schoolId==null){
            return null;
        }

        SplitClassLayerCourse selectObject=new SplitClassLayerCourse();
        selectObject.setTaskId(taskId);
        selectObject.setSchoolid(schoolId);
        List<SplitClassLayerCourse> splitClassLayerCourseList=this.selectByObject(selectObject,false);
        HashMap<Long,SplitClassLayerCourse> id2LayerCourse=new HashMap();
        if(CollectionUtils.isNotEmpty(splitClassLayerCourseList)){
            for(SplitClassLayerCourse splitClassLayerCourse:splitClassLayerCourseList){
                id2LayerCourse.put(splitClassLayerCourse.getCourseId(),splitClassLayerCourse);
            }
        }

        List result=new LinkedList();
        List<SelectedInfo> selectedInfoList= electiveStudentSelectedService.getCourseSelected(taskId,null,schoolId,false);
        if(CollectionUtils.isNotEmpty(selectedInfoList)){
            for(SelectedInfo selectedInfo:selectedInfoList){
                SplitClassLayerCourse splitClassLayerCourse=new SplitClassLayerCourse();
                splitClassLayerCourse.setCourseId(selectedInfo.getCourseId());
                splitClassLayerCourse.setCourseName(selectedInfo.getCourseName());
                SplitClassLayerCourse layerCourse=id2LayerCourse.get(selectedInfo.getCourseId());
                if(layerCourse!=null && layerCourse.getLayerCount()!=null){
                    splitClassLayerCourse.setLayerCount(layerCourse.getLayerCount());
                }else {
                    splitClassLayerCourse.setLayerCount(1);
                }
                splitClassLayerCourse.setSelectedCount(selectedInfo.getSelectedCount());
                splitClassLayerCourse.setSelectedMaleCount(selectedInfo.getMaleCount());
                result.add(splitClassLayerCourse);
            }
            return result;
        }
        return null;
    }

    public List<CourseTime> getComposeByTaskFromCache(Long taskId,Long schoolId){

        Object cacheObject=redisService.getValue(String.format("%s_%s_%s",BlueContants.prefix_courseLayerCompose,schoolId,taskId));
        if(cacheObject!=null){
            return JSONArray.parseArray(cacheObject.toString(),CourseTime.class);
        }else {
            List<CourseTime> result=getComposeByTask(taskId,schoolId);
            if(CollectionUtils.isNotEmpty(result)){
                redisService.setValue(String.format("%s_%s_%s",BlueContants.prefix_courseLayerCompose,schoolId,taskId),JSONArray.toJSONString(result),BlueContants.week);
            }
            return result;
        }

    }


    public HashMap<Long, List<CourseTime>> getClassCompose(Long taskId, Long schoolId) {
        //获取整个任务的课程选择人数和学时组合
        List<CourseTime> courseTimeList = splitClassTimeService.queryCompose(taskId, schoolId);
        if (CollectionUtils.isEmpty(courseTimeList)) {
            return null;
        }
        //获取班级课程分层的选课人数
        HashMap<Long, HashMap<String, Integer>> classLayerMap = getClassLayerMap(taskId, schoolId);
        if (classLayerMap == null || classLayerMap.keySet().size() == 0) {
            return null;
        }

        HashMap<Long, List<CourseTime>> result = new HashMap();

        for (Long classId : classLayerMap.keySet()) {
            HashMap course2Selected = classLayerMap.get(classId);
            if (course2Selected == null || course2Selected.keySet().size() == 0) {
                continue;
            }
            List classCourseTimeList=new LinkedList();
            for (CourseTime courseTime : courseTimeList) {

                if (CollectionUtils.isEmpty(courseTime.getSelectedCourseInfo())) {
                    continue;
                }
                Long selectCount = 0L;
                for (CourseTime subCourseTime : courseTime.getSelectedCourseInfo()) {
                    Long selectedCount = course2Selected.get(subCourseTime.getCourseName())==null?0:Long.decode(course2Selected.get(subCourseTime.getCourseName()).toString());
                    subCourseTime.setSelectedCount(selectedCount);
                    selectCount = Math.min(selectCount == 0 ? subCourseTime.getSelectedCount() : selectCount, subCourseTime.getSelectedCount());
                }

                if(selectCount==0){
                    continue;
                }

                courseTime.setSelectedCount(selectCount);
                classCourseTimeList.add(courseTime);
            }
            result.put(classId, classCourseTimeList);

        }

        return result;
    }


    //获取任务所有班级数据，每个班级所有的课程分层数据，返回结果如下："{16:{"生物":1,"历史_优秀":1,"政治_优秀":1,"地理":1}}"
    public HashMap<Long,HashMap<String,Integer>> getClassLayerMap(Long taskId,Long schoolId){

        //获取用户的分层数据
        List<SplitClassLayerStudent> splitClassLayerStudents=splitClassLayerStudentService.selectByTaskId(taskId,schoolId);
        HashMap<Long,String> uid2LayerInfo=new HashMap<>();
        if(CollectionUtils.isNotEmpty(splitClassLayerStudents)){
            for(SplitClassLayerStudent splitClassLayerStudent:splitClassLayerStudents){
                if(StringUtils.isNotBlank(splitClassLayerStudent.getLayerInfo())){
                    uid2LayerInfo.put(splitClassLayerStudent.getUserid(),splitClassLayerStudent.getLayerInfo());
                }
            }
        }

        //根据用户的选课信息，拼接课程选择数据
        List<ElectiveStudentSelected> electiveStudentSelectedList=electiveStudentSelectedService.selectByTaskId(taskId,schoolId,true);
        if(CollectionUtils.isEmpty(electiveStudentSelectedList)){
            return null;
        }
        //根据班级列表获取各个班级的数据，然后获取
        HashMap<Long,HashMap<String,Integer>> class2Couse2Count=new HashMap();//用于存放 班级下的- 课程-分层 选择个数
        for(ElectiveStudentSelected electiveStudentSelected:electiveStudentSelectedList){
            if(class2Couse2Count.get(electiveStudentSelected.getClassId())==null){
                class2Couse2Count.put(electiveStudentSelected.getClassId(),new HashMap<String,Integer>());
            }
            HashMap<String,Integer> course2SelectedCount=class2Couse2Count.get(electiveStudentSelected.getClassId());

            if(CollectionUtils.isEmpty(electiveStudentSelected.getCourseNameList())){
                continue;
            }

            for(BlueCourse blueCourse:electiveStudentSelected.getCourseNameList()){
                String courseName=blueCourse.getName();
                if(uid2LayerInfo.get(electiveStudentSelected.getUserId())!=null){//用户被分层
                  JSONObject layerInfoJsonObject=JSONObject.parseObject(uid2LayerInfo.get(electiveStudentSelected.getUserId()));
                  if(layerInfoJsonObject!=null && layerInfoJsonObject.getString(blueCourse.getName())!=null){
                      courseName=String.format("%s_%s",blueCourse.getName(),layerInfoJsonObject.getString(blueCourse.getName()));
                  }
                }

                if(course2SelectedCount.get(courseName)==null){
                    course2SelectedCount.put(courseName,0);
                }

                course2SelectedCount.put(courseName,course2SelectedCount.get(courseName)+1);
            }
        }

        return class2Couse2Count;
    }


    /**
     *
     * @param taskId
     * @param schoolId
     * @return
     */
    public List<CourseTime> getComposeByTask(Long taskId,Long schoolId){

        if(taskId==null || schoolId==null){
            return null;
        }

        ElectiveTask electiveTask=electiveTaskService.selectById(taskId,schoolId);
        if(electiveTask==null || StringUtils.isBlank(electiveTask.getCourseIds())){
            return null;
        }
        //查询科目分层数据
        List<SplitClassLayerCourse> splitClassLayerCourseList=this.selectByTaskId(taskId,schoolId);
        List result=new LinkedList();
        HashMap<Long,SplitClassLayerCourse> courseId2LayerMap=new HashMap();//用于后续判定课程是否进行了分层
        String[] layerInfos={};//总的分层明细
        if(CollectionUtils.isNotEmpty(splitClassLayerCourseList)){
            for(SplitClassLayerCourse splitClassLayerCourse:splitClassLayerCourseList){
                courseId2LayerMap.put(splitClassLayerCourse.getCourseId(),splitClassLayerCourse);
            }
            SplitClassLayerInfo splitClassLayerInfo=splitClassLayerInfoService.selectByTaskId(taskId,schoolId);
            if(splitClassLayerInfo!=null && StringUtils.isNotBlank(splitClassLayerInfo.getNames())){
                layerInfos=splitClassLayerInfo.getNames().split(",");
            }
        }

        List<Long> courseIds=BlueStringUtils.convertString2Num(electiveTask.getCourseIds(),",");
        if(CollectionUtils.isEmpty(courseIds)){
            return null;
        }
        //获取任务总的课程集合
        List<ElectivePublishCourse> electivePublishCourseList=electivePublishCourseService.selectByTaskId(taskId, (short) TaskTypeEnum.Course.getKey(),schoolId);

        if(CollectionUtils.isEmpty(electivePublishCourseList)){
            return null;
        }

        HashMap<Long,List> courseName2CourseList=new HashMap();//课程名称对应的课程，由于分层的原因，可能存在一个课程名称对应好几个课程的现象
        HashMap<String,CourseTime> courseName2Time=new HashMap();
        List courseNameList=new LinkedList();//课程名称列表
        for (Long courseId : courseIds) {
            SplitClassLayerCourse splitClassLayerCourse = courseId2LayerMap.get(courseId);
            //当前科目是否分层，如果未层，则直接获取科目数据即可。
            if (splitClassLayerCourse != null && splitClassLayerCourse.getLayerCount()!=null && StringUtils.isNotBlank(splitClassLayerCourse.getLayerResultConfig())){
                JSONArray layerResultArray=JSONArray.parseArray(splitClassLayerCourse.getLayerResultConfig());
                for(int i=0;i<splitClassLayerCourse.getLayerCount();i++){
                    String courseName=String.format("%s_%s",splitClassLayerCourse.getCourseName(),layerInfos[i]);
                    CourseTime courseTime=new CourseTime();
                    courseTime.setCourseName(courseName);
                    if(layerResultArray!=null && layerResultArray.get(i)!=null){
                        courseTime.setSelectedCount(JSONObject.parseObject(layerResultArray.get(i).toString()).getLong("studentCount"));
                    }
                    courseTime.setCourseId(courseId);
                    courseName2Time.put(courseTime.getCourseName(),courseTime);
                    List courseTempList=null;
                    if(courseName2CourseList.get(splitClassLayerCourse.getCourseId())==null){
                        courseTempList=new LinkedList();
                    }else {
                        courseTempList=courseName2CourseList.get(splitClassLayerCourse.getCourseId());
                    }
                    courseTempList.add(courseTime);
                    courseName2CourseList.put(splitClassLayerCourse.getCourseId(),courseTempList);
                    courseNameList.add(courseTime.getCourseName());
                }

            } else {
                CourseTime courseTime=new CourseTime();
                courseTime.setCourseId(courseId);
                courseTime.setCourseName(blueCourseService.selectByPrimaryKey(courseId,schoolId,false).getName());
                courseTime.setSelectedCount(redisService.getSetSize(String.format("%s_%s_%s_%s",BlueContants.prefix_selected_oneSubject_total,schoolId,taskId,courseId)));
                courseName2Time.put(courseTime.getCourseName(),courseTime);
                courseNameList.add(courseTime.getCourseName());
            }
        }

        //根据课程名称列表创建组合，这个只是粗粒度的组合，还需要对不符合条件的组合过滤掉
        List<ElectivePublishCourse> publishCourseList=electivePublishCourseService.getCombination(courseNameList,taskId,schoolId,false);
        List<String> courseComposeList=new LinkedList();
        ElectiveRuleObject electiveRuleObject=electivePublishCourseService.getRequiredCourse(taskId,schoolId);
        List requestCourseList=electiveRuleObject.getRequiredCourse();
        //获取课程规则数据
        List requiredCourseNames=new LinkedList();
        if(CollectionUtils.isNotEmpty(requestCourseList)){
            List<BlueCourse> requiredCourseList=blueCourseService.selectByIds(StringUtils.join(requestCourseList,","),schoolId);
            if(CollectionUtils.isNotEmpty(requiredCourseList)){
                for(BlueCourse blueCourse:requiredCourseList){
                    requiredCourseNames.add(blueCourse.getName());
                }
            }
        }
        //去除非法数据
        if(CollectionUtils.isNotEmpty(publishCourseList)){
            for(ElectivePublishCourse electivePublishCourse:publishCourseList){
                Set courseSet=new HashSet();
                for(String courseName:electivePublishCourse.getCourseIds().split(",")){
                    courseSet.add(courseName.split("_")[0]);//要求规则命名的时候 不能包含_
                }

                if(!courseSet.containsAll(requiredCourseNames)){
                    continue;
                }

                courseComposeList.add(electivePublishCourse.getCourseIds());
            }
        }
        //根据组合设定规则，产生组合
        for(String courses:courseComposeList){
           CourseTime courseTime=new CourseTime();
           courseTime.setCourseName(courses);
           List<CourseTime> subCourseList=new LinkedList();
           long selectCount=0;
           for(String courseName:courses.split(",")){
               CourseTime subItem=courseName2Time.get(courseName);
               if(subItem==null || subItem.getSelectedCount()==0){
                   break;
               }
               subCourseList.add(subItem);
               selectCount=Math.min(selectCount==0?subItem.getSelectedCount():selectCount,subItem.getSelectedCount());
           }
           //当存在课程获取不到课时信息的时候，
           if(subCourseList.size()!=courses.split(",").length || selectCount==0){
               continue;
           }
           courseTime.setSelectedCourseInfo(subCourseList);
           courseTime.setSelectedCount(selectCount);
           result.add(courseTime);

        }

        return result;
    }

    @Override
    public BaseMapper getBaseMapper() {
        return this.splitClassLayerCourseMapper;
    }

    @Override
    public void clearCache(Long schoolId,Object... extend) {
        clearTemplet(extend!=null? (Long) extend[0] :null,schoolId);
        clearLayerCompose(extend!=null? (Long) extend[0] :null,schoolId);
    }

    public void clearTemplet(Long taskId,Long schoolId){
        if(taskId!=null && taskId>0){
            redisService.vagueDelete(String.format("%s_%s_%s",ossTempletPrefix,schoolId,taskId));
        }else {
            redisService.vagueDelete(String.format("%s_%s",ossTempletPrefix,schoolId));
        }
    }

    public void clearLayerCompose(Long taskId,Long schoolId){
        if(taskId!=null && taskId>0){
            redisService.vagueDelete(String.format("%s_%s_%s",BlueContants.prefix_courseLayerCompose,schoolId,taskId));
        }else {
            redisService.vagueDelete(String.format("%s_%s",BlueContants.prefix_courseLayerCompose,schoolId));
        }
    }

}
